<template>
	<div style="display: flex;flex-direction: column;">
		<div>
			<map style="width: 100%;height:calc(100vh - 170px)" :markers="markers" :longitude="endLocation.longitude"
				:latitude="endLocation.latitude" :show-scale="true" :polyline="polyline"
				:include-points="markers"></map>
		</div>
		<div>
			<div>
				<div style="font-size: 16px;font-weight: bold;text-align: center;margin: 10px;">最近一次定位数据</div>
				<div style="text-align: center;margin-bottom: 10px;">
					地址：{{ lastLocation.address ? lastLocation.address : '暂无数据' }}
				</div>
				<div style="display: flex;justify-content: space-around;">
					<div>经度：{{ lastLocation.longitude ? lastLocation.longitude.toFixed(6) : 0 }}</div>
					<div>纬度：{{ lastLocation.latitude ? lastLocation.latitude.toFixed(6) : 0 }}</div>
				</div>
			</div>
			<div style="display: flex;justify-content: space-around;padding: 10px 0;">
				<up-button style="width: 40%;" :disabled="isTracking" type="primary"
					@click="startTracking">开始追踪</up-button>
				<up-button style="width: 40%;" :disabled="!isTracking" type="error"
					@click="stopTracking">停止追踪</up-button>
			</div>
		</div>
	</div>
	<up-toast ref="uToastRef"></up-toast>
</template>

<script setup>
import { nextTick, reactive, ref, onBeforeUnmount } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { getGeocode, getAddress } from '@/utils/map.js'
import { pushPosition } from '@/api/driver.js'

/* 数据 */
const uToastRef = ref(null)
// 运单id
const id = ref('')
// 终点地址
const endAddress = ref('广州南站')
// 终点坐标
const endLocation = reactive({})
// 地图上的点
const markers = reactive([])
// 点的label
const label = {
	content: '',
	color: '#fff',
	fontSize: 16,
	padding: 10,
	borderRadius: 5,
	bgColor: '#1e90ff',
	display: 'ALWAYS',//BYCLICK
	anchorX: -26,
	anchorY: 5
}
// 是否开始追踪
const isTracking = ref(false)
// 定时器
const timer = ref(null)
// 轨迹
const polyline = reactive([{
	points: [],
	color: '#1e90ff',
	width: 6,
}])
// 最近一次的位置
const lastLocation = reactive({})



/* 方法 */
// 停止追踪
const stopTracking = () => {
	isTracking.value = false
	if (timer.value) clearInterval(timer.value)
	uToastRef.value.show({
		position: 'top',
		message: '已停止追踪您的位置',
		type: 'warning'
	})
}
// 判断是否到达目的地
const isExtremelyClose = (lat1, lng1, lat2, lng2) => {
	// 经纬度差值阈值（约 1 米）
	const threshold = 0.05 // 约 5.5 千米
	return Math.abs(lat1 - lat2) < threshold && Math.abs(lng1 - lng2) < threshold
}
// 获取定位
const getLocation = async () => {
	return new Promise((resolve, reject) => {
		uni.getLocation({
			type: 'gcj02',
			isHighAccuracy: true,
			timeout: 10000,
			highAccuracyExpireTime: 5000,
			success: (res) => resolve(res),
			fail: (err) => reject(err)
		})
	})
}
// 获取定位后方法封装
const handleLocation = async () => {
	uToastRef.value.show({
		message: '正在获取位置',
		type: 'loading',
		duration: -1
	})
	let res = await getLocation()
	uToastRef.value.hide()

	if (!(res.latitude && res.longitude)) return

	// 推送位置信息到服务器
	let { success } = await pushPosition({
		shipId: id.value,
		lon: res.longitude,
		lat: res.latitude
	})
	if (!success) {
		// 考虑到司机可能在长隧道，一次不成功也不会中断定时器，只会这次位置不记录
		uToastRef.value.show({
			position: 'top',
			message: '该次位置信息上传失败',
			type: 'error'
		})
		return
	}

	uToastRef.value.show({
		message: '正在获取位置详情',
		type: 'loading',
		duration: -1
	})
	let address = await getAddress(res.latitude, res.longitude)
	uToastRef.value.hide()

	if (!address.originalData) return
	markers.push({
		id: Date.now(),
		latitude: res.latitude,
		longitude: res.longitude,
		callout: {
			...label,
			content: address.originalData.result.formatted_address,
			display: 'BYCLICK'
		}
	})
	polyline[0].points.push({
		latitude: res.latitude,
		longitude: res.longitude
	})
	lastLocation.latitude = res.latitude
	lastLocation.longitude = res.longitude
	lastLocation.address = address.originalData.result.formatted_address
}
// 开始追踪
const startTracking = async () => {
	if (isTracking.value) return
	try {
		let { authSetting } = await uni.getSetting()
		if (authSetting && authSetting['scope.userLocation']) {
			// 已授权定位权限
			isTracking.value = true
			// 首次定位
			await handleLocation()
			// //设置定时器
			timer.value = setInterval(async () => {
				if (!isTracking.value) return
				await handleLocation()
				if (isExtremelyClose(lastLocation.latitude,
					lastLocation.longitude,
					endLocation.latitude,
					endLocation.longitude)) {
					isTracking.value = false
					uToastRef.value.show({
						position: 'top',
						message: '已到达目的地',
						type: 'success'
					})
					clearInterval(timer.value)
				}
			}, 60000)
		} else {
			// 未授权，请求授权
			let { errMsg } = await uni.authorize({
				scope: 'scope.userLocation'
			})
			if (errMsg === 'authorize:ok') {
				// 已授权定位权限
				isTracking.value = true
				await handleLocation()
				// 首次定位
				await handleLocation()
				// //设置定时器
				timer.value = setInterval(async () => {
					if (!isTracking.value) return
					await handleLocation()
					if (isExtremelyClose(lastLocation.latitude,
						lastLocation.longitude,
						endLocation.latitude,
						endLocation.longitude)) {
						isTracking.value = false
						uToastRef.value.show({
							position: 'top',
							message: '已到达目的地',
							type: 'success'
						})
						clearInterval(timer.value)
					}
				}, 60000)
			} else {
				uToastRef.value.show({
					position: 'top',
					message: '获取定位权限失败',
					type: 'error'
				})
			}
		}
	} catch (err) {
		// 拒绝授权
		if (err.errMsg.includes('auth deny')) {
			uni.showModal({
				title: '提示',
				content: '需要位置权限才能使用该功能，请前往设置开启',
				success: (res) => {
					if (res.confirm) {
						// 跳转到小程序设置页
						uni.openSetting()
					}
				}
			})
		} else {
			uToastRef.value.show({
				position: 'top',
				message: '获取定位失败' + err.errMsg,
				type: 'error'
			})
		}
	}
}
// 获取终点
const getEnd = async () => {
	try {
		uToastRef.value.show({
			message: '正在初始化地图...',
			type: 'loading',
			duration: -1
		})
		let res = await getGeocode(endAddress.value)
		uToastRef.value.hide()
		if (res.result.location) {
			endLocation.latitude = res.result.location.lat
			endLocation.longitude = res.result.location.lng
			markers.push({
				id: Date.now(),
				latitude: res.result.location.lat,
				longitude: res.result.location.lng,
				label: {
					...label,
					content: '终点'
				}
			})
		}
	} catch (err) {
		uToastRef.value.show({
			position: 'top',
			message: '初始化失败，请重试',
			type: 'error'
		})
	}

}
// 初始化封装
const init = async () => {
	await getEnd()
}



/* 钩子 */
onLoad(async (options) => {
	id.value = options.id
	if (options.endAddress) {
		let address = JSON.parse(options.endAddress)
		endAddress.value = address.provinceText + address.cityText + address.countyText + (address.text ? address.text : '')
	}
	await nextTick()
	await init()
})
onBeforeUnmount(() => {
	if (timer.value) clearInterval(timer.value)
})


</script>

<style></style>
